home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / sysstat / sysstat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-02  |  9.3 KB  |  342 lines

  1. /*
  2.  * sysStat.c --
  3.  *
  4.  *    Statistics generation for system calls, and a hook for other
  5.  *    system-related commands.
  6.  *
  7.  * Copyright 1986, 1988 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/cmds/sysstat/RCS/sysstat.c,v 1.8 92/06/02 13:21:38 kupfer Exp $ SPRITE (Berkeley)";
  19. #endif not lint
  20.  
  21. #include <sprite.h>
  22. #include <spriteTime.h>
  23. #include <fs.h>
  24. #include <sysStats.h>
  25. #include <status.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <option.h>
  29. #include <host.h>
  30. #include <kernel/sysSysCall.h>
  31. #include <kernel/trace.h>
  32. #include <kernel/sync.h>
  33. #include <kernel/sched.h>
  34. #include <kernel/mach.h>
  35.  
  36. #include "syscalls.h"
  37.  
  38. /*
  39.  * Variables for options.
  40.  */
  41.  
  42. int countCalls = 0;
  43. #define JUST_CALLS    1
  44. #define CALLS_AND_TIMES    2
  45.  
  46. int resetCount = 0;
  47. int printVersion = 0;
  48. int doSyncStat = 0;
  49. int doSchedStat = 0;
  50. int enableProfiling = -1;
  51.  
  52. Option optionArray[] = {
  53.     {OPT_CONSTANT(JUST_CALLS), "c", (Address)&countCalls,
  54.      "Print the number of system calls invoked."},
  55.     {OPT_TRUE, "l", (Address)&doSyncStat, "Print lock (Sync) statistics"},
  56.     {OPT_INT, "p", (Address)&enableProfiling,
  57.      "Set or clear the flag that controls system call profiling"},
  58.     {OPT_TRUE, "R", (Address)&resetCount,
  59.      "Reset the count of system calls to 0."},
  60.     {OPT_CONSTANT(CALLS_AND_TIMES), "t", (Address)&countCalls,
  61.      "Print the number of system calls invoked and the time they took."},
  62.     {OPT_TRUE, "v", (Address)&printVersion,
  63.      "Print compilation timestamp for the kernel (DEFAULT)."},
  64.     {OPT_TRUE, "x", (Address)&doSchedStat, "Print scheduling statistics"},
  65. };
  66.  
  67. /*
  68.  * Constants used by tracing routines:
  69.  *     PROC_NUM_EVENTS - the number of valid trace events for proc.\
  70.  */
  71.  
  72. #define PROC_NUM_EVENTS 5
  73.  
  74.  
  75. /*
  76.  *----------------------------------------------------------------------
  77.  *
  78.  * main --
  79.  *
  80.  *    Driver.
  81.  *
  82.  * Results:
  83.  *    None.
  84.  *
  85.  * Side effects:
  86.  *    Variable.
  87.  *
  88.  *----------------------------------------------------------------------
  89.  */
  90.  
  91.  
  92. main(argc, argv)
  93.     int argc;
  94.     char *argv[];
  95. {
  96.     ReturnStatus status = SUCCESS;
  97.     char          version[128];
  98.     Sys_MachineInfo    machineInfo;
  99.     int            numProcessors;
  100.     int exitStatus = 0;
  101.  
  102.     (void) Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray),
  103.              OPT_ALLOW_CLUSTERING);
  104.     if (! (printVersion || countCalls || resetCount)) {
  105.     printVersion = 1;
  106.     }
  107.     if (printVersion) {
  108.     if (Sys_Stats(SYS_GET_VERSION_STRING, sizeof(version), version) ==
  109.         SUCCESS) {
  110.         int virtualHost, physicalHost;
  111.         Host_Entry *hostPtr;
  112.  
  113.         if ((Proc_GetHostIDs(&virtualHost, &physicalHost) != SUCCESS) ||
  114.         ((hostPtr = Host_ByID(physicalHost)) == (Host_Entry *)NULL)) {
  115.         (void) printf("%s\n", version);
  116.         } else {
  117.         char *cPtr;
  118.         /*
  119.          * Nuke domain suffix and print hostname with kernel version.
  120.          */
  121.         for (cPtr = hostPtr->name ; *cPtr ; cPtr++) {
  122.             if (*cPtr == '.') {
  123.             *cPtr = '\0';
  124.             break;
  125.             }
  126.         }
  127.         (void) printf("%-20s %s\n", hostPtr->name, version);
  128.         }
  129.         (void) fflush(stdout);
  130.     }
  131.     }
  132.  
  133.     if (countCalls) {
  134.     status = PrintNumCalls(countCalls);
  135.     }
  136.     if (status != SUCCESS) {
  137.     fprintf(stderr, "Couldn't get stats about Sprite calls: %s\n",
  138.         Stat_GetMsg(status));
  139.     exitStatus = 1;
  140.     }
  141.  
  142.     if (resetCount) {
  143.     status = Sys_Stats(SYS_SYS_CALL_STATS, 0, (Address) NULL);
  144.     }
  145.     if (status != SUCCESS) {
  146.     fprintf(stderr, "Couldn't reset stats about Sprite calls: %s\n",
  147.         Stat_GetMsg(status));
  148.     exitStatus = 1;
  149.     }
  150.  
  151.     if (enableProfiling != -1) {
  152.     status = Sys_Stats(SYS_SYS_CALL_STATS_ENABLE, enableProfiling,
  153.                (Address)NULL);
  154.     }
  155.     if (status != SUCCESS) {
  156.     fprintf(stderr, "Couldn't %s profiling for Sprite calls: %s\n",
  157.         (enableProfiling ? "enable" : "disable"),
  158.         Stat_GetMsg(status));
  159.     exitStatus = 1;
  160.     }
  161.  
  162.     status = Sys_GetMachineInfo(sizeof(Sys_MachineInfo), &machineInfo);
  163.     if (status != SUCCESS) {
  164.     printf("Sys_GetMachineInfo failed: %s.\n", Stat_GetMsg(status));
  165.     exit(1);
  166.     }
  167.     numProcessors = machineInfo.processors;
  168.     if (doSyncStat) {
  169.     PrintSyncStats(numProcessors);
  170.     }
  171.     if (doSchedStat) {
  172.     PrintSchedStats(numProcessors);
  173.     }
  174.  
  175.     exit(exitStatus);
  176. }
  177.  
  178.  
  179. /*
  180.  *----------------------------------------------------------------------
  181.  *
  182.  * PrintNumCalls --
  183.  *
  184.  *    Print the number of system calls invoked by processes since the last
  185.  *    time the counter was reset.
  186.  *
  187.  * Results:
  188.  *    The return status from Sys_Stats is returned.
  189.  *
  190.  * Side effects:
  191.  *    The number of calls is output.
  192.  *
  193.  *----------------------------------------------------------------------
  194.  */
  195.  
  196. ReturnStatus
  197. PrintNumCalls(callType)
  198.     int callType;        /* just calls, or times too */
  199. {
  200.     Address buffer;    /* Buffer to hold counters */
  201.     int bufSize;
  202.     ReturnStatus status;
  203.     int i;
  204.     int numForeign = 0;
  205.     int numLocal = 0;
  206.     register int *numCalls;    /* array of counts (one per call) */
  207.     Time *totalTimes;        /* array of times (one per call) */
  208.     int msec;
  209.     int numAlloc;        /* number of entries to allocate space for */
  210.  
  211.     /*
  212.      * Allocate an array to hold the numbers from the kernel.  This will 
  213.      * either be an array of counters or an array of counters followed by 
  214.      * an array of Time values.
  215.      */
  216.     numAlloc = sysCallArraySize / sizeof(SysCallInfo);
  217.     bufSize = numAlloc * (callType == JUST_CALLS
  218.               ? sizeof(int)
  219.               : sizeof(int) + sizeof(Time));
  220.     buffer = malloc((unsigned) bufSize);
  221.  
  222.     /* 
  223.      * Now get the numbers from the kernel.
  224.      */
  225.     status = Sys_Stats((callType == JUST_CALLS
  226.             ? SYS_SYS_CALL_STATS
  227.             : SYS_SYS_CALL_TIMES),
  228.                numAlloc, buffer);
  229.     if (status != SUCCESS) {
  230.     fprintf(stderr, "Couldn't get %s: %s\n",
  231.         (callType == JUST_CALLS ? "counters" : "counters and times"),
  232.          Stat_GetMsg(status));
  233.     return(status);
  234.     }
  235.  
  236.     /* 
  237.      * Print out the results.  The format depends on whether we give the 
  238.      * time as well as the count.
  239.      */
  240.     numCalls = (int *) buffer;
  241.     totalTimes = (Time *)((int *)buffer + numAlloc);
  242.  
  243.     for (i = 0; i < numAlloc; i++) {
  244.     if (callType == JUST_CALLS) {
  245.         (void) printf("%d\t%-30s", numCalls[i], sysCallArray[i].name);
  246.         if (sysCallArray[i].local) {
  247.         numLocal += numCalls[i];
  248.         (void) printf("local\n");
  249.         } else {
  250.         numForeign += numCalls[i];
  251.         (void) printf("remote\n");
  252.         }
  253.     } else {
  254.         (void)printf("%d\t%d.%03d\t", numCalls[i], 
  255.              totalTimes[i].seconds,
  256.              (totalTimes[i].microseconds + 500) / 1000);
  257.         if (numCalls[i] != 0) {
  258.         Time_Divide(totalTimes[i], numCalls[i],
  259.                 &totalTimes[i]);
  260.         }
  261.         msec = (int)Time_ToMs(totalTimes[i]);
  262.         if (msec < 10 && !Time_EQ(totalTimes[i], time_ZeroSeconds)) {
  263.         (void)printf("(%d.%03d ms avg)\t",
  264.                  msec, totalTimes[i].microseconds % 1000);
  265.         } else {
  266.         (void)printf("(%d ms avg)\t",
  267.                  (int)(Time_ToMs(totalTimes[i]) + 0.5));
  268.         }
  269.         (void)printf("%-30s\n", sysCallArray[i].name);
  270.     }
  271.     }
  272.     if (callType == JUST_CALLS) {
  273.     (void) printf("\n\nTotal number of calls: %d local, %d remote.\n",
  274.               numLocal, numForeign);
  275.     (void) printf("%d/%d = %6.2f%% remote.\n",
  276.               numForeign, numForeign + numLocal, 
  277.               ((double) numForeign) / (numForeign + numLocal) * 100.);
  278.     }
  279.     return(0);
  280. }
  281.  
  282. PrintSyncStats(numProcessors)
  283.     int    numProcessors;    
  284. {
  285.     Sync_Instrument    syncStat[MACH_MAX_NUM_PROCESSORS];
  286.     ReturnStatus    status;
  287.     int            i;
  288.  
  289.     status = Sys_Stats(SYS_SYNC_STATS, sizeof(syncStat), syncStat);
  290.     if (status != SUCCESS) {
  291.     return;
  292.     }
  293.     printf("Sync Statistics\n");
  294.     for (i = 0; i < numProcessors; i++) {
  295.     printf("Processor %d\n", i);
  296.     printf("numWakeups = %d\n", syncStat[i].numWakeups);
  297.     printf("numWakeupCalls = %d\n", syncStat[i].numWakeupCalls);
  298.     printf("numSpuriousWakeups = %d\n", syncStat[i].numSpuriousWakeups);
  299.     printf("numLocks = %d\n", syncStat[i].numLocks);
  300.     printf("numUnlocks = %d\n", syncStat[i].numUnlocks);
  301.     printf("Misses on sched_Mutex in idle loop = %d\n",
  302.             syncStat[i].sched_MutexMiss);
  303.     }
  304. }
  305.  
  306. PrintSchedStats(numProcessors)
  307.     int numProcessors;
  308. {
  309.     Sched_Instrument schedStat;
  310.     ReturnStatus    status;
  311.     int            i;
  312.  
  313.     status = Sys_Stats(SYS_SCHED_STATS, 0, &schedStat);
  314.     if (status != SUCCESS) {
  315.     return;
  316.     }
  317.     printf("Sched Statistics\n");
  318.     for (i = 0; i < numProcessors; i++) {
  319.     printf("Processor %d\n", i);
  320.     printf("numContextSwitches = %d\n", 
  321.             schedStat.processor[i].numContextSwitches);
  322.     printf("numFullSwitches    = %d\n", schedStat.processor[i].numFullCS);
  323.     printf("numInvoluntary     = %d\n", 
  324.             schedStat.processor[i].numInvoluntarySwitches);
  325. #ifdef notdef
  326.     printf("onDeckSelf       = %d\n",
  327.             schedStat.processor[i].onDeckSelf);
  328.     printf("onDeckOther       = %d\n",
  329.             schedStat.processor[i].onDeckOther);
  330. #endif notdef
  331.     printf("Idle Time          = %d.%06d seconds\n",
  332.            schedStat.processor[i].idleTime.seconds,
  333.            schedStat.processor[i].idleTime.microseconds);
  334.         printf("Idle ticks = %d * 2^32 + %d.\n", 
  335.             schedStat.processor[i].idleTicksOverflow,
  336.             schedStat.processor[i].idleTicksLow);
  337.     printf("Idle ticks/sec = %d.\n", 
  338.             schedStat.processor[i].idleTicksPerSecond);
  339.     }
  340. }
  341.  
  342.